import uthread
import uix
import mathUtil
import base
import util
import blue
import service
import re
import state
import math
import uiutil
import uicls
import menu
import uiconst
cgre = re.compile('chargeGroup\\d{1,2}')

class ModuleButton(uicls.Icon):
    __guid__ = 'xtriui.ModuleButton'
    __notifyevents__ = ['OnStateChange',
     'OnItemChange',
     'OnModuleRepaired',
     'OnAmmoInBankChanged',
     'OnFailLockTarget',
     'OnChargeBeingLoadedToModule']
    __update_on_reload__ = 1
    __cgattrs__ = []
    __loadingcharges__ = []
    __chargesizecache__ = {}
    default_name = 'ModuleButton'
    default_ignoreSize = True

    def ApplyAttributes(self, attributes):
        uicls.Icon.ApplyAttributes(self, attributes)



    def _OnClose(self):
        if (getattr(self, 'invCookie', None) is not None):
            sm.GetService('inv').Unregister(self.invCookie)
        uicls.Icon._OnClose(self)



    def init(self):
        self.def_effect = None
        self.charge = None
        self.target = None
        self.waitingForActiveTarget = 0
        self.changingAmmo = 0
        self.reloadingAmmo = False
        self.online = False
        self.goingOnline = 0
        self.stateManager = None
        self.autorepeat = 0
        self.autoreload = 0
        self.sr.accuracyTimer = None
        self.quantity = None
        self.invReady = 1
        self.invCookie = None
        self.isInvItem = 1
        self.isBeingRepaired = 0
        self.blinking = 0
        self.blinkingDamage = 0
        self.effect_activating = 0
        self.typeName = ''
        self.ramp_active = False
        self.isMaster = 0
        self.isPendingUnlockForDeactivate = False
        sm.RegisterNotify(self)



    def Setup(self, moduleinfo, grey = None):
        if not len(self.__cgattrs__):
            self.__cgattrs__.extend([ a.attributeID for a in cfg.dgmattribs if (cgre.match(a.attributeName) is not None) ])
        invType = cfg.invtypes.Get(moduleinfo.typeID)
        group = cfg.invtypes.Get(moduleinfo.typeID).Group()
        self.id = moduleinfo.itemID
        self.sr.moduleInfo = moduleinfo
        self.locationFlag = moduleinfo.flagID
        self.stateManager = sm.StartService('godma').GetStateManager()
        self.grey = grey
        self.typeName = uix.GetItemName(self.sr.moduleInfo)
        for each in ['glow',
         'busy',
         'hilite',
         'quantityParent',
         'damageState',
         'overloadBtn',
         'stackParent',
         'ramps',
         'leftRamp',
         'leftShadowRamp',
         'rightRamp',
         'rightShadowRamp',
         'groupHighlight']:
            obj = uiutil.GetChild(self.parent.parent, each)
            setattr(self.sr, each, obj)

        self.sr.leftShadowRamp.state = self.sr.rightShadowRamp.state = uix.UI_HIDDEN
        self.sr.ramps.opacity = 0.85
        self.sr.qtylabel = uicls.Label(text='', parent=self.sr.quantityParent, left=3, top=0, autowidth=False, width=30, letterspace=1, fontsize=9, state=uiconst.UI_DISABLED, uppercase=1, idx=0)
        self.sr.stacklabel = uicls.Label(text='', parent=self.sr.stackParent, left=5, top=0, autowidth=False, width=30, letterspace=1, fontsize=9, state=uiconst.UI_DISABLED, uppercase=1, idx=0, shadow=[], color=(1.0, 1.0, 1.0, 1))
        icon = uicls.Container(self.sr.overloadBtn)
        icon.sr.hint = mls.UI_CMD_TOGGLEOVERLOAD
        icon.OnClick = self.ToggleOverload
        icon.OnMouseDown = self.OLButtonDown
        icon.OnMouseUp = self.OLButtonUp
        icon.OnMouseExit = self.OLMouseExit
        self.sr.overloadButton = icon
        self.sr.damageState = uicls.Container(self.sr.damageState)
        if cfg.IsChargeCompatible(moduleinfo):
            self.invCookie = sm.GetService('inv').Register(self)
        self.autoreload = settings.char.autoreload.Get(self.sr.moduleInfo.itemID, 1)
        if (group.categoryID == const.categoryCharge):
            self.SetCharge(moduleinfo)
        else:
            self.SetCharge(None)
        self.autoreload = settings.char.autoreload.Get(self.sr.moduleInfo.itemID, 1)
        for key in moduleinfo.effects.iterkeys():
            effect = moduleinfo.effects[key]
            if self.IsEffectActivatible(effect):
                self.def_effect = effect
                if effect.isActive:
                    if effect.isDeactivating:
                        self.isDeactivating = True
                        self.SetDeactivating()
                    else:
                        self.SetActive()
            if (effect.effectName == 'online'):
                if effect.isActive:
                    self.ShowOnline()
                else:
                    self.ShowOffline()

        self.autoreload = settings.char.autoreload.Get(self.sr.moduleInfo.itemID, 1)
        godma = sm.StartService('godma')
        self.isBeingRepaired = godma.GetStateManager().IsModuleBeingRepaired(self.id)
        if self.isBeingRepaired:
            self.SetRepairing()
        repeat = settings.char.autorepeat.Get(self.sr.moduleInfo.itemID, -1)
        if (group.groupID in (const.groupMiningLaser, const.groupStripMiner)):
            self.SetRepeat(1000)
        elif (repeat != -1):
            self.SetRepeat(repeat)
        else:
            repeatSet = 0
            for key in self.sr.moduleInfo.effects.iterkeys():
                effect = self.sr.moduleInfo.effects[key]
                if self.IsEffectRepeatable(effect):
                    self.SetRepeat(1000)
                    repeatSet = 1
                    break

            if not repeatSet:
                self.SetRepeat(0)
        self.autoreload = settings.char.autoreload.Get(self.sr.moduleInfo.itemID, 1)
        if not getattr(self, 'isDeactivating', False):
            self.state = uix.UI_NORMAL
        self.slaves = self.stateManager.GetSlaveModules(self.sr.moduleInfo.itemID)
        moduleDamage = self.GetModuleDamage()
        if moduleDamage:
            self.SetDamage((moduleDamage / moduleinfo.hp))
        else:
            self.SetDamage(0.0)
        self.Draggable_blockDrag = 0
        self.autoreload = settings.char.autoreload.Get(self.sr.moduleInfo.itemID, 1)
        uthread.new(self.BlinkIcon)



    def OLButtonDown(self, btn, *args):
        btn.top = 6



    def OLButtonUp(self, btn, *args):
        btn.top = 5



    def OLMouseExit(self, btn, *args):
        btn.top = 5



    def ToggleOverload(self, *args):
        if settings.user.ui.Get('lockOverload', 0):
            eve.Message('error')
            eve.Message('LockedOverloadState')
            return 
        for key in self.sr.moduleInfo.effects.iterkeys():
            effect = self.sr.moduleInfo.effects[key]
            if (effect.effectCategory == const.dgmEffOverload):
                active = effect.isActive
                if active:
                    eve.Message('click')
                    effect.Deactivate()
                else:
                    eve.Message('click')
                    effect.Activate()




    def SetCharge(self, charge):
        if (charge and (charge.stacksize != 0)):
            if ((self.charge is None) or (charge.typeID != self.charge.typeID)):
                self.ChangeIcon(typeID=charge.typeID, size=48)
            self.charge = charge
            self.stateManager.ChangeAmmoTypeForModule(self.sr.moduleInfo.itemID, charge.typeID)
            self.id = charge.itemID
            self.UpdateChargeQuantity(charge)
        else:
            self.ChangeIcon(typeID=self.sr.moduleInfo.typeID, size=48)
            self.sr.qtylabel.parent.state = uix.UI_HIDDEN
            self.quantity = 0
            self.id = self.sr.moduleInfo.itemID
            self.charge = None
        self.tripass = eve.rot.GetInstance('res:/UI/Pass/linear.blue')
        try:
            self.CheckOverload()
            self.CheckOnline()
            self.CheckMasterSlave()
        except:
            uix.LogWarn('Module.SetCharge', self.id)



    def UpdateChargeQuantity(self, charge):
        if (charge is self.charge):
            if (cfg.invtypes.Get(charge.typeID).groupID in cfg.GetCrystalGroups()):
                self.sr.qtylabel.parent.state = uix.UI_HIDDEN
                return 
            self.quantity = charge.stacksize
            self.sr.qtylabel.text = ('%s' % util.FmtAmt(charge.stacksize))
            self.sr.qtylabel.parent.state = uix.UI_DISABLED



    def ShowGroupHighlight(self):
        self.dragging = True
        self.sr.groupHighlight.state = uiconst.UI_DISABLED
        uthread.new(self.PulseGroupHighlight)



    def StopShowingGroupHighlight(self):
        self.dragging = False
        self.sr.groupHighlight.state = uiconst.UI_HIDDEN



    def PulseGroupHighlight(self):
        pulseSize = 0.4
        opacity = 1.0
        startTime = blue.os.GetTime()
        while self.dragging:
            self.sr.groupHighlight.opacity = opacity
            blue.pyos.synchro.Sleep(200)
            if ((not self) or self.destroyed):
                break
            sinWave = math.cos((float((blue.os.GetTime() - startTime)) / (0.5 * const.SEC)))
            opacity = min(((sinWave * pulseSize) + (1 - (pulseSize / 2))), 1)




    def SetDamage(self, damage):
        if ((not damage) or (damage < 0.0001)):
            self.sr.damageState.state = uix.UI_HIDDEN
            return 
        _damage = damage
        y = 192
        if (_damage > 0.5):
            y = 128
            _damage -= 0.5
        if (_damage <= 0.125):
            x = 192
        elif (_damage <= 0.25):
            x = 128
        elif (_damage <= 0.375):
            x = 64
        else:
            x = 0
        self.sr.damageState.rectLeft = x
        self.sr.damageState.rectTop = y
        self.sr.damageState.state = uix.UI_NORMAL
        self.sr.damageState.sr.hint = ('%s: %d%%' % (mls.UI_GENERIC_DAMAGE, ((self.sr.moduleInfo.damage / self.sr.moduleInfo.hp) * 100)))
        sm.GetService('ui').BlinkSpriteA(self.sr.damageState, 1.0, (2000 - (1000 * damage)), 2, passColor=0)



    def GetVolume(self):
        if self.charge:
            return cfg.GetItemVolume(self.charge, 1)



    def IsMine(self, rec):
        ret = ((rec.locationID == eve.session.shipid) and ((rec.flagID == self.locationFlag) and (cfg.invtypes.Get(rec.typeID).Group().Category().id == const.categoryCharge)))
        return ret



    def AddItem(self, rec):
        if (cfg.invtypes.Get(rec.typeID).categoryID == const.categoryCharge):
            self.SetCharge(rec)



    def UpdateItem(self, rec, change):
        if (cfg.invtypes.Get(rec.typeID).categoryID == const.categoryCharge):
            self.SetCharge(rec)



    def RemoveItem(self, rec):
        if (cfg.invtypes.Get(rec.typeID).categoryID == const.categoryCharge):
            if (self.charge and (rec.itemID == self.id)):
                self.SetCharge(None)



    def GetShell(self):
        return eve.GetInventoryFromId(eve.session.shipid)



    def GetMatchingAmmo(self, lTypeID, ignoreLoading = 0):
        lRS = cfg.dgmtypeattribs.get(lTypeID, [])
        lAttribs = util.IndexedRows(lRS, ('attributeID',))
        if lAttribs.has_key(const.attributeChargeSize):
            wantChargeSize = lAttribs[const.attributeChargeSize].value
        else:
            wantChargeSize = 0
        chargeGroups = []
        for attributeID in self.__cgattrs__:
            if lAttribs.has_key(attributeID):
                groupID = lAttribs[attributeID].value
                if (groupID != 0):
                    chargeGroups.append(groupID)

        if ignoreLoading:
            return [ item for item in self.GetShell().ListCargo() if (item.groupID in chargeGroups) ]
        else:
            return [ item for item in self.GetShell().ListCargo() if (item.groupID in chargeGroups) ]



    def IsCorrectChargeSize(self, item, wantChargeSize):
        if not self.__chargesizecache__.has_key(item.typeID):
            cRS = cfg.dgmtypeattribs.get(item.typeID, [])
            cAttribs = util.IndexedRows(cRS, ('attributeID',))
            if cAttribs.has_key(const.attributeChargeSize):
                gotChargeSize = cAttribs[const.attributeChargeSize].value
            else:
                gotChargeSize = 0
            self.__chargesizecache__[item.typeID] = gotChargeSize
        else:
            gotChargeSize = self.__chargesizecache__[item.typeID]
        if (wantChargeSize != gotChargeSize):
            return 0
        else:
            return 1



    def UnloadToCargo(self, itemID):
        self.reloadingAmmo = True
        try:
            sm.GetService('godma').GetStateManager().UnloadChargeToContainer(itemID, (session.shipid), const.flagCargo)

        finally:
            self.reloadingAmmo = False




    def ChangeAmmoType(self, typeID, quantity):
        itemID = None
        (chargeTypeID, chargeQuantity, roomForReload,) = self.GetChargeReloadInfo(ignoreCharge=1)
        matchingAmmo = [ (item.stacksize, item) for item in self.GetMatchingAmmo(self.sr.moduleInfo.typeID) if (item.typeID == typeID) ]
        matchingAmmo = uiutil.SortListOfTuples(matchingAmmo)
        matchingAmmo.reverse()
        sm.GetService('godma').GetStateManager().LoadChargeToModule(self.sr.moduleInfo.itemID, typeID, chargeItems=matchingAmmo)



    def ReloadAmmo(self, itemID, quantity, preferSingletons = False):
        if not quantity:
            return 
        self.reloadingAmmo = True
        lastChargeTypeID = self.stateManager.GetAmmoTypeForModule(self.sr.moduleInfo.itemID)
        try:
            self.stateManager.LoadChargeToModule(self.sr.moduleInfo.itemID, lastChargeTypeID, preferSingletons=preferSingletons)

        finally:
            self.reloadingAmmo = False




    def ReloadAllAmmo(self):
        uicore.cmd.CmdReloadAmmo()



    def BlinkIcon(self, time = None):
        if (self.destroyed or self.blinking):
            return 
        startTime = blue.os.GetTime()
        if (time is not None):
            timeToBlink = (time * 10000)
        while (self.changingAmmo or (self.reloadingAmmo or (self.waitingForActiveTarget or (self.goingOnline or time)))):
            if (time is not None):
                if ((blue.os.GetTime() - startTime) > timeToBlink):
                    break
            blue.pyos.synchro.Sleep(250)
            if self.destroyed:
                return 
            self.color.a = 0.25
            blue.pyos.synchro.Sleep(250)
            if self.destroyed:
                return 
            self.color.a = 1.0

        if self.destroyed:
            return 
        self.blinking = 0
        self.CheckOverload()
        self.CheckOnline()



    def ChangeAmmo(self, itemID, quantity, ammoType):
        if not quantity:
            return 
        self.changingAmmo = 1
        try:
            sm.GetService('godma').GetStateManager().LoadChargeToModule(itemID, ammoType, qty=quantity)

        finally:
            if (self and (not self.destroyed)):
                self.changingAmmo = 0




    def DoNothing(self, *args):
        return 



    def CopyItemIDToClipboard(self, itemID):
        blue.pyos.SetClipboardData(str(itemID))



    def GetMenu(self):
        ship = sm.GetService('godma').GetItem(eve.session.shipid)
        if (ship is None):
            return []
        else:
            m = []
            if (eve.session.role & (service.ROLE_GML | service.ROLE_WORLDMOD)):
                if cfg.IsChargeCompatible(self.sr.moduleInfo):
                    m += [(('Launcher: ' + str(self.sr.moduleInfo.itemID)),
                      self.CopyItemIDToClipboard,
                      (self.sr.moduleInfo.itemID))]
                    if (self.id != self.sr.moduleInfo.itemID):
                        m += [(('Charge: ' + str(self.id)),
                          self.CopyItemIDToClipboard,
                          (self.id)), None]
                else:
                    m += [(str(self.id),
                      self.CopyItemIDToClipboard,
                      (self.id)), None]
                m += sm.GetService('menu').GetGMTypeMenu(self.sr.moduleInfo.typeID, itemID=self.id, divs=True, unload=True)
            moduleType = cfg.invtypes.Get(self.sr.moduleInfo.typeID)
            groupID = moduleType.groupID
            if cfg.IsChargeCompatible(self.sr.moduleInfo):
                (chargeTypeID, chargeQuantity, roomForReload,) = self.GetChargeReloadInfo()
                matchingAmmo = self.GetMatchingAmmo(self.sr.moduleInfo.typeID)
                ammoList = {}
                ammoSingletonList = {}
                for item in matchingAmmo:
                    if (item.typeID != chargeTypeID):
                        if item.singleton:
                            ammoSingletonList[item.typeID] = (ammoSingletonList.get(item.typeID, []) + [item])
                        else:
                            ammoList[item.typeID] = (ammoList.get(item.typeID, []) + [item])

                if (roomForReload > 0):
                    reloadCandidates = [ (item.stacksize,
                     item.itemID,
                     min(item.stacksize, roomForReload)) for item in matchingAmmo if (item.typeID == chargeTypeID) ]
                    reloadSingletonCandidates = [ (item.itemID, min(item.stacksize, roomForReload)) for item in matchingAmmo if (item.typeID == chargeTypeID) ]
                else:
                    reloadCandidates = []
                    reloadSingletonCandidates = []
                noOfModules = (1 if (self.slaves is None) else (len(self.slaves) + 1))
                noOfCharges = sum([ cand[1] for cand in reloadSingletonCandidates ])
                if (noOfCharges >= noOfModules):
                    text = (('%s (%s)' % (mls.UI_CMD_RELOAD_USED, cfg.invtypes.Get(chargeTypeID).typeName)), menu.ACTIONSGROUP)
                    m.append((text,
                     self.ReloadAmmo,
                     (reloadSingletonCandidates[-1][0],
                      reloadSingletonCandidates[-1][1],
                      True)))
                noOfCharges = sum([ cand[0] for cand in reloadCandidates ])
                if (noOfCharges >= noOfModules):
                    reloadCandidates.sort()
                    text = (('%s (%s)' % (mls.UI_CMD_RELOAD, cfg.invtypes.Get(chargeTypeID).typeName)), menu.ACTIONSGROUP)
                    m.append((text,
                     self.ReloadAmmo,
                     (reloadCandidates[-1][1], reloadCandidates[-1][2])))
                    m.append((mls.UI_CMD_RELOADALL, self.ReloadAllAmmo))
                m.append(None)
                if (self.charge is not None):
                    m.append((mls.UI_CMD_UNLOADTOCARGO,
                     self.UnloadToCargo,
                     (self.charge.itemID)))
                    m.append(None)
                temp = []
                if len(ammoSingletonList):
                    for l in ammoSingletonList.itervalues():
                        item = l[0]
                        text = (('%s (%s)' % (cfg.invtypes.Get(item.typeID).name, mls.UI_GENERIC_USED)), menu.ACTIONSGROUP)
                        temp.append((text, (text,
                          self.ChangeAmmoType,
                          (item.typeID, item.stacksize))))

                m.extend(uiutil.SortListOfTuples(temp))
                temp = []
                if len(ammoList):
                    for l in ammoList.itervalues():
                        sumqty = sum([ each.stacksize for each in l ])
                        item = l[0]
                        qty = int(((moduleType.capacity / cfg.GetItemVolume(item, 1)) + 1e-07))
                        if qty:
                            text = (('%s [%s]' % (cfg.invtypes.Get(item.typeID).name, util.FmtAmt(sumqty))), menu.ACTIONSGROUP)
                            temp.append((text, (text,
                              self.ChangeAmmoType,
                              (item.typeID, item.stacksize))))

                m.extend(uiutil.SortListOfTuples(temp))
                m.append(None)
                if (self.autoreload == 0):
                    m.append((mls.UI_CMD_AUTORELOADON,
                     self.SetAutoReload,
                     (1,)))
                else:
                    m.append((mls.UI_CMD_AUTORELOADOFF,
                     self.SetAutoReload,
                     (0,)))
            overloadLock = settings.user.ui.Get('lockOverload', 0)
            itemID = self.sr.moduleInfo.itemID
            slaves = self.stateManager.GetModulesSlaves(itemID)
            for key in self.sr.moduleInfo.effects.iterkeys():
                effect = self.sr.moduleInfo.effects[key]
                if (self.IsEffectRepeatable(effect) and (groupID not in (const.groupMiningLaser, const.groupStripMiner))):
                    if (self.autorepeat == 0):
                        m.append((mls.UI_CMD_AUTOREPEATON,
                         self.SetRepeat,
                         (1000,)))
                    else:
                        m.append((mls.UI_CMD_AUTOREPEATOFF,
                         self.SetRepeat,
                         (0,)))
                if (effect.effectName == 'online'):
                    m.append(None)
                    if not slaves:
                        if effect.isActive:
                            m.append((mls.UI_CMD_PUTOFFLINE,
                             self.ChangeOnline,
                             (0,)))
                        else:
                            m.append((mls.UI_CMD_PUTONLINE,
                             self.ChangeOnline,
                             (1,)))
                if ((not overloadLock) and (effect.effectCategory == const.dgmEffOverload)):
                    active = effect.isActive
                    if active:
                        m.append(((mls.UI_CMD_TOGGLEOVERLOAD + (' (%s)' % mls.UI_GENERIC_ACTIVE)),
                         self.Overload,
                         (0, effect)))
                    else:
                        m.append(((mls.UI_CMD_TOGGLEOVERLOAD + (' (%s)' % mls.UI_GENERIC_INACTIVE)),
                         self.Overload,
                         (1, effect)))
                    m.append((mls.UI_CMD_OVERLOADRACK,
                     self.OverloadRack,
                     ()))
                    m.append((mls.UI_CMD_STOPOVERLOADRACK,
                     self.StopOverloadRack,
                     ()))

            moduleDamage = self.GetModuleDamage()
            if moduleDamage:
                if self.isBeingRepaired:
                    m.append((mls.UI_CMD_CANCELREPAIR,
                     self.CancelRepair,
                     ()))
                else:
                    m.append((mls.UI_CMD_REPAIR,
                     self.RepairModule,
                     ()))
            if slaves:
                m.append((mls.UI_CMD_UNLINK,
                 self.UnlinkModule,
                 ()))
            m += [(mls.UI_CMD_SHOWINFO,
              sm.GetService('info').ShowInfo,
              (self.sr.moduleInfo.typeID,
               self.sr.moduleInfo.itemID,
               0,
               self.sr.moduleInfo))]
            return m



    def RepairModule(self):
        success = self.stateManager.RepairModule(self.sr.moduleInfo.itemID)
        if self.slaves:
            for slave in self.slaves:
                success = (self.stateManager.RepairModule(slave) or success)

        if (success == True):
            self.isBeingRepaired = True
            self.SetRepairing()



    def CancelRepair(self):
        sm.GetService('godma').GetStateManager().StopRepairModule(self.sr.moduleInfo.itemID)



    def OnFailLockTarget(self, tid, *args):
        self.waitingForActiveTarget = 0



    def OnModuleRepaired(self, itemID):
        if (itemID == self.sr.moduleInfo.itemID):
            self.RemoveRepairing()
            self.isBeingRepaired = False



    def OnAmmoInBankChanged(self, masterID):
        slaves = self.stateManager.GetModulesSlaves(masterID)
        if (self.sr.moduleInfo.itemID in slaves):
            self.SetCharge(self.sr.moduleInfo)



    def OnChargeBeingLoadedToModule(self, itemIDs, chargeTypeID, time):
        if (self.sr.moduleInfo.itemID not in itemIDs):
            return 
        chargeGroupID = self.stateManager.GetType(chargeTypeID).groupID
        eve.Message('LauncherLoadDelay', {'ammo': (GROUPID, chargeGroupID),
         'launcher': (GROUPID, self.sr.moduleInfo.groupID),
         'time': (time / 1000)})
        self.BlinkIcon(time)



    def UnlinkModule(self):
        self.stateManager.DestroyWeaponBank(self.sr.moduleInfo.itemID)



    def Overload(self, onoff, eff):
        if onoff:
            eff.Activate()
        else:
            eff.Deactivate()



    def OverloadRack(self):
        sm.GetService('godma').OverloadRack(self.sr.moduleInfo.itemID)



    def StopOverloadRack(self):
        sm.GetService('godma').StopOverloadRack(self.sr.moduleInfo.itemID)



    def GetChargeReloadInfo(self, ignoreCharge = 0):
        moduleType = cfg.invtypes.Get(self.sr.moduleInfo.typeID)
        lastChargeTypeID = self.stateManager.GetAmmoTypeForModule(self.sr.moduleInfo.itemID)
        if (self.charge and (not ignoreCharge)):
            chargeTypeID = self.charge.typeID
            chargeQuantity = self.charge.stacksize
        elif (lastChargeTypeID is not None):
            chargeTypeID = lastChargeTypeID
            chargeQuantity = 0
        else:
            chargeTypeID = None
            chargeQuantity = 0
        if (chargeTypeID is not None):
            roomForReload = int((((moduleType.capacity / cfg.invtypes.Get(chargeTypeID).volume) - chargeQuantity) + 1e-07))
        else:
            roomForReload = 0
        return (chargeTypeID,
         chargeQuantity,
         roomForReload)



    def SetAutoReload(self, on):
        settings.char.autoreload.Set(self.sr.moduleInfo.itemID, on)
        self.autoreload = on
        self.AutoReload()



    def AutoReload(self, force = 0, useItemID = None, useQuant = None):
        if (self.reloadingAmmo is not False):
            return 
        if ((not cfg.IsChargeCompatible(self.sr.moduleInfo)) or (not (self.autoreload or force))):
            return 
        (chargeTypeID, chargeQuantity, roomForReload,) = self.GetChargeReloadInfo()
        if (((chargeQuantity > 0) and (not force)) or (roomForReload <= 0)):
            return 
        shiplayer = uicore.layer.shipui
        if not shiplayer:
            return 
        self.stateManager.LoadChargeToModule(self.sr.moduleInfo.itemID, chargeTypeID)
        uthread.new(self.CheckPending)



    def OnItemChange(self, item, change):
        if ((not self) or (self.destroyed or (not getattr(self, 'sr', None)))):
            return 
        if not ((const.ixQuantity in change) or (const.ixStackSize in change)):
            return 
        if (const.ixQuantity in change):
            log.LogTraceback('Quantity changing on shipmodulebutton')
        if ((self.reloadingAmmo == item.itemID) and (not sm.GetService('invCache').IsItemLocked(self, item.itemID))):
            shiplayer = uicore.layer.shipui
            reloadsByID = shiplayer.sr.reloadsByID
            self.reloadingAmmo = True
            if reloadsByID[item.itemID].balance:
                reloadsByID[item.itemID].send(None)
            else:
                del reloadsByID[item.itemID]



    def CheckPending(self):
        shiplayer = uicore.layer.shipui
        if not shiplayer:
            return 
        blue.pyos.synchro.Sleep(1000)
        if (shiplayer and shiplayer):
            shiplayer.CheckPendingReloads()



    def CheckOverload(self):
        if ((not self) or self.destroyed):
            return 
        isActive = False
        hasOverloadEffect = False
        if not util.HasAttrs(self, 'sr', 'moduleInfo', 'effects'):
            return 
        for key in self.sr.moduleInfo.effects.iterkeys():
            effect = self.sr.moduleInfo.effects[key]
            if (effect.effectCategory == const.dgmEffOverload):
                if effect.isActive:
                    isActive = True
                hasOverloadEffect = True

        if hasOverloadEffect:
            self.sr.overloadButton.top = 5
            if self.online:
                self.sr.overloadButton.rectLeft = 96
                if isActive:
                    self.sr.overloadButton.rectTop = 0
                else:
                    self.sr.overloadButton.rectTop = 16
                self.sr.overloadButton.state = uix.UI_NORMAL
            else:
                self.sr.overloadButton.rectLeft = 64
            self.sr.overloadButton.rectTop = 0
            self.sr.overloadButton.state = uix.UI_DISABLED
        else:
            self.sr.overloadButton.top = 6
            self.sr.overloadButton.state = uix.UI_DISABLED
            self.sr.overloadButton.rectLeft = 64
            self.sr.overloadButton.rectTop = 0



    def CheckMasterSlave(self):
        if ((not self) or self.destroyed):
            return 
        itemID = self.sr.moduleInfo.itemID
        slaves = self.stateManager.GetModulesSlaves(itemID)
        if slaves:
            self.sr.stackParent.state = uix.UI_DISABLED
            self.sr.stacklabel.text = (len(slaves) + 1)



    def CheckOnline(self, sound = 0):
        if ((not self) or self.destroyed):
            return 
        if not util.HasAttrs(self, 'sr', 'moduleInfo', 'effects'):
            return 
        for key in self.sr.moduleInfo.effects.keys():
            effect = self.sr.moduleInfo.effects[key]
            if (effect.effectName == 'online'):
                if effect.isActive:
                    self.ShowOnline()
                    if sound:
                        eve.Message('OnLogin')
                else:
                    self.ShowOffline()
                return 




    def ChangeOnline(self, on = 1):
        uthread.new(self._ChangeOnline, on)



    def _ChangeOnline(self, on):
        masterID = self.stateManager.IsInWeaponBank(self.sr.moduleInfo.itemID)
        if masterID:
            if not on:
                ret = eve.Message('CustomQuestion', {'header': 'OFFLINE',
                 'question': "When offlining this module you will destroy the weapons bank it's in. Are you sure you want to offline it? "}, uix.YESNO)
                if (ret != uix.ID_YES):
                    return 
        elif ((not on) and (eve.Message('PutOffline', {}, uix.YESNO) != uix.ID_YES)):
            return 
        for key in self.sr.moduleInfo.effects.keys():
            effect = self.sr.moduleInfo.effects[key]
            if (effect.effectName == 'online'):
                if on:
                    effect.Activate()
                    self.goingOnline = 1
                    uthread.new(self.BlinkIcon)
                    blue.pyos.synchro.Sleep(5000)
                    if ((not self) or self.destroyed):
                        return 
                    self.goingOnline = 0
                else:
                    self.ShowOffline(1)
                    effect.Deactivate()
                return 




    def ShowOverload(self, on):
        self.CheckOverload()



    def ShowOnline(self):
        self.isMaster = 0
        if self.AreModulesOffline():
            self.ShowOffline()
            return 
        self.online = True
        if self.grey:
            self.color.a = 0.1
        elif not self.goingOnline:
            self.color.a = 1.0
        self.CheckOverload()



    def ShowOffline(self, ping = 0):
        self.online = False
        self.goingOnline = 0
        if self.grey:
            self.color.a = 0.1
        else:
            self.color.a = 0.25
        if ping:
            eve.Message('OnLogin')
        self.CheckOverload()
        self.state = uix.UI_NORMAL



    def AreModulesOffline(self):
        slaves = self.stateManager.GetModulesSlaves(self.sr.moduleInfo.itemID)
        if not slaves:
            return False
        else:
            self.isMaster = 1
            onlineEffect = self.stateManager.GetEffect(self.sr.moduleInfo.itemID, 'online')
            if ((onlineEffect is None) or (not onlineEffect.isActive)):
                return True
            for slave in slaves:
                onlineEffect = self.stateManager.GetEffect(slave, 'online')
                if ((onlineEffect is None) or (not onlineEffect.isActive)):
                    return True

            return False



    def IsEffectRepeatable(self, effect, activatibleKnown = 0):
        if not ((activatibleKnown or self.IsEffectActivatible(effect)) and effect.item.disallowRepeatingActivation):
            return (effect.durationAttributeID is not None)
        return 0



    def IsEffectActivatible(self, effect):
        return (effect.isDefault and ((effect.effectName != 'online') and (effect.effectCategory in (const.dgmEffActivation, const.dgmEffTarget))))



    def SetRepeat(self, num):
        settings.char.autorepeat.Set(self.sr.moduleInfo.itemID, num)
        self.autorepeat = num



    def GetDefaultEffect(self):
        if ((not self) or self.destroyed):
            return 
        if ((self.sr is None) or ((self.sr.moduleInfo is None) or (not self.stateManager.IsItemLoaded(self.sr.moduleInfo.itemID)))):
            return 
        for key in self.sr.moduleInfo.effects.iterkeys():
            effect = self.sr.moduleInfo.effects[key]
            if self.IsEffectActivatible(effect):
                return effect




    def _OnClick(self, *args):
        if ((not self) or (self.goingOnline or self.IsBeingDragged())):
            return 
        ctrlRepeat = 0
        if eve.triapp.uilib.Key(uix.VK_CONTROL):
            ctrlRepeat = 1000
        self.Click(ctrlRepeat)



    def Click(self, ctrlRepeat = 0):
        if self.waitingForActiveTarget:
            sm.GetService('target').CancelTargetOrder(self)
            self.waitingForActiveTarget = 0
        elif (self.def_effect is None):
            uix.LogWarn('No default Effect available for this moduletypeID:', self.sr.moduleInfo.typeID)
        elif not self.online:
            if getattr(self, 'isMaster', None):
                eve.Message('ClickOffllineGroup')
            else:
                eve.Message('ClickOffllineModule')
        elif self.def_effect.isActive:
            self.DeactivateEffect(self.def_effect)
        elif not self.effect_activating:
            self.activationTimer = base.AutoTimer(500, self.ActivateEffectTimer)
            self.effect_activating = 1
            self.ActivateEffect(self.def_effect, ctrlRepeat=ctrlRepeat)



    def ActivateEffectTimer(self, *args):
        self.effect_activating = 0
        self.activationTimer = None



    def OnEndDrag_(self, *args):
        uthread.new(uicore.layer.shipui.ResetSwapMode)



    def GetDragData(self, *args):
        if settings.user.ui.Get('lockModules', 0):
            return []
        else:
            if self.charge:
                fakeNode = uix.GetItemData(self.charge, 'icons')
                fakeNode.isCharge = 1
            else:
                fakeNode = uix.GetItemData(self.sr.moduleInfo, 'icons')
                fakeNode.isCharge = 0
            fakeNode.__guid__ = 'xtriui.ShipUIModule'
            fakeNode.slotFlag = self.sr.moduleInfo.flagID
            shift = eve.triapp.uilib.Key(uix.VK_SHIFT)
            uicore.layer.shipui.StartDragMode(self.sr.moduleInfo.itemID, self.sr.moduleInfo.typeID)
            return [fakeNode]



    def OnDropData(self, dragObj, nodes):
        uix.LogInfo('Module.OnDropData', self.id)
        flag1 = self.sr.moduleInfo.flagID
        flag2 = None
        for node in nodes:
            if (node.Get('__guid__', None) == 'xtriui.ShipUIModule'):
                flag2 = node.slotFlag
                break

        if (flag1 == flag2):
            return 
        if (flag2 is not None):
            uicore.layer.shipui.ChangeSlots(flag1, flag2)
            return 
        multiLoadCharges = True
        chargeTypeID = None
        chargeItems = []
        for node in nodes:
            if not hasattr(node, 'rec'):
                return 
            chargeItem = node.rec
            if not hasattr(chargeItem, 'categoryID'):
                return 
            if (chargeItem.categoryID != const.categoryCharge):
                continue
            if (chargeTypeID is None):
                chargeTypeID = chargeItem.typeID
            if (chargeItem.typeID == chargeTypeID):
                chargeItems.append(chargeItem)

        if (len(chargeItems) > 0):
            self.stateManager.DropLoadChargeToModule(self.sr.moduleInfo.itemID, chargeTypeID, chargeItems=chargeItems)



    def _OnMouseDown(self, *args):
        uicls.Icon._OnMouseDown(self, *args)
        uix.LogInfo('Module._OnMouseDown', self.id)
        if (getattr(self, 'downTop', None) is not None):
            return 
        self.downTop = self.parent.parent.top
        self.parent.parent.top += 2



    def _OnMouseUp(self, *args):
        uicls.Icon._OnMouseUp(self, *args)
        if ((not self) or self.destroyed):
            return 
        uix.LogInfo('Module._OnMouseUp', self.id)
        if (getattr(self, 'downTop', None) is not None):
            self.parent.parent.top = self.downTop
            self.downTop = None



    def _OnMouseEnter(self, *args):
        self.HiliteOn()
        uthread.pool('ShipMobuleButton::MouseEnter', self.MouseEnter)



    def MouseEnter(self, *args):
        if (self.destroyed or (sm.GetService('godma').GetItem(self.sr.moduleInfo.itemID) is None)):
            return 
        uix.LogInfo('Module._OnMouseEnter', self.id)
        eve.Message('NeocomButtonEnter')
        self.ShowAccuracy()
        self.sr.accuracyTimer = base.AutoTimer(1000, self.ShowAccuracy)
        uthread.pool('ShipMobuleButton::_OnMouseEnter-->UpdateTargetingRanges', sm.GetService('tactical').UpdateTargetingRanges, self.sr.moduleInfo)



    def _OnMouseExit(self, *args):
        uix.LogInfo('Module._OnMouseExit', self.id)
        self.HiliteOff()
        sm.ScatterEvent('OnShowAccuracy', None)
        self.sr.accuracyTimer = None
        self._OnMouseUp(None)



    def _OnMouseMove(self, *args):
        uicls.Icon._OnMouseMove(self, *args)
        uthread.pool('ShipModuleButton::MouseMove', self.UpdateInfo)



    def ShowAccuracy(self):
        self.UpdateInfo()
        sm.ScatterEvent('OnShowAccuracy', self.GetAccuracy)



    def UpdateInfo(self):
        if ((not self) or self.destroyed):
            return 
        if not self.stateManager.IsItemLoaded(self.id):
            return 
        self.sr.hint = ''
        if (eve.triapp.uilib.mouseOver != self):
            self.sr.accuracyTimer = None
            return 
        info = ''
        slaves = self.stateManager.GetModulesSlaves(self.sr.moduleInfo.itemID)
        if slaves:
            numModules = (len(slaves) + 1)
            info += ('<b>%s</b><br>' % (mls.UI_SHARED_WEAPONLINK_WEAPONGROUP % {'numModules': numModules}))
        info += ('%s: %s' % (mls.UI_GENERIC_TYPE, self.typeName))
        defEff = self.GetDefaultEffect()
        if defEff:
            status = mls.UI_GENERIC_INACTIVE
            if defEff.isActive:
                status = mls.UI_GENERIC_ACTIVE
        else:
            status = ''
        info += ('<br>%s: %s' % (mls.UI_GENERIC_STATUS, status))
        if self.goingOnline:
            info += (', %s' % mls.UI_INFLIGHT_GOINGONLINE.lower())
        if self.waitingForActiveTarget:
            info += (', %s' % mls.UI_INFLIGHT_WAITINGFORACTIVETARGET.lower())
        if self.changingAmmo:
            info += (', %s' % mls.UI_INFLIGHT_CHANGINGAMMO.lower())
        if self.reloadingAmmo:
            info += (', %s' % mls.UI_INFLIGHT_RELOADINGAMMO.lower())
        if cfg.IsChargeCompatible(self.sr.moduleInfo):
            if (self.charge and self.charge.typeID):
                chargetype = cfg.invtypes.Get(self.charge.typeID)
                info += ('<br>' + (mls.UI_INFLIGHT_CHARGEPCS % {'qty': util.FmtAmt(self.charge.stacksize),
                 'type': chargetype.name}))
            else:
                info += ('<br>%s' % mls.UI_INFLIGHT_CHARGENOCHARGE)
        for key in self.sr.moduleInfo.effects.iterkeys():
            effect = self.sr.moduleInfo.effects[key]
            if (effect.effectCategory == const.dgmEffOverload):
                if effect.isActive:
                    info += ('<br>%s: %s' % (mls.UI_GENERIC_OVERLOADSTATUS, mls.UI_GENERIC_ACTIVE))
                else:
                    info += ('<br>%s: %s' % (mls.UI_GENERIC_OVERLOADSTATUS, mls.UI_GENERIC_INACTIVE))

        moduleDamage = self.GetModuleDamage()
        if moduleDamage:
            info += ('<br>%s: %d%%' % (mls.UI_GENERIC_DAMAGE, ((moduleDamage / self.sr.moduleInfo.hp) * 100)))
        accuracy = self.GetAccuracy()
        acc = ''
        if (accuracy is not None):
            info += ('<br>%s: %.2f' % (mls.UI_GENERIC_ACCURACY, accuracy[0]))
        if self.charge:
            godmaInfo = sm.GetService('godma').GetItem(self.charge.itemID)
            if (godmaInfo and godmaInfo.crystalsGetDamaged):
                info += ('<br>%s: %.2f' % (mls.UI_GENERIC_DAMAGE, godmaInfo.damage))
        pos = uicore.layer.shipui.GetPosFromFlag(self.sr.moduleInfo.flagID)
        if pos:
            hiMedLo = ('High', 'Medium', 'Low')[pos[0]]
            slotno = (pos[1] + 1)
            shortcut = uicore.cmd.GetShortcutStringByFuncName(('CmdActivate%sPowerSlot%i' % (hiMedLo, slotno)))
            if not shortcut:
                shortcut = mls.UI_GENERIC_NONE
            info += ('<br>%s: %s' % (mls.UI_GENERIC_SHORTCUT, shortcut))
        if (self and getattr(self, 'sr', None)):
            self.sr.hint = info



    def GetModuleDamage(self):
        moduleDamage = self.sr.moduleInfo.damage
        if (self.slaves is None):
            return moduleDamage
        else:
            maxDamage = moduleDamage
            for slaveID in self.slaves:
                slave = self.stateManager.GetItem(slaveID)
                if (slave is None):
                    continue
                damage = self.stateManager.GetItem(slaveID).damage
                if (damage > maxDamage):
                    maxDamage = damage

            return maxDamage



    def GetAccuracy(self, targetID = None):
        if ((self is None) or self.destroyed):
            return 
        else:
            return 
        if (targetID is None):
            targetID = sm.GetService('target').GetActiveTargetID()
        if (targetID is None):
            return 
        for key in self.sr.moduleInfo.effects.keys():
            effect = self.sr.moduleInfo.effects[key]
            if effect.isDefault:
                if (effect.effectName == 'useMissiles'):
                    if (self.charge is None):
                        return 
                    effect = self.sr.moduleInfo.GetChargeEffect(self.charge.typeID)
                    if (effect is None):
                        return 
                if (effect.trackingSpeedAttributeID is None):
                    if (effect.rangeAttributeID is not None):
                        maxRange = effect.range
                else:
                    trackingSpeed = effect.trackingSpeed
                    falloff = effect.falloff
                    maxRange = effect.range
                    bp = sm.GetService('michelle').GetBallpark()
                    if (bp is not None):
                        return bp.GetAccuracy(eve.session.shipid, targetID, maxRange, falloff, trackingSpeed, self.sr.moduleInfo.signatureRadius)
                    else:
                        return 
                return 




    def SetActive(self):
        self.sr.glow.state = uix.UI_DISABLED
        sm.GetService('ui').BlinkSpriteA(self.sr.glow, 0.75, 1000, None, passColor=0)
        self.effect_activating = 0
        self.activationTimer = None
        self.state = uix.UI_NORMAL
        if settings.user.ui.Get('showCycleTimer', 1):
            self.ActivateRamps()



    def SetDeactivating(self):
        self.sr.glow.state = uix.UI_HIDDEN
        self.sr.busy.state = uix.UI_DISABLED
        sm.GetService('ui').BlinkSpriteA(self.sr.busy, 0.75, 1000, None, passColor=0)
        self.state = uix.UI_DISABLED
        if settings.user.ui.Get('showCycleTimer', 1):
            self.DeActivateRamps()



    def SetIdle(self):
        self.sr.glow.state = uix.UI_HIDDEN
        self.sr.busy.state = uix.UI_HIDDEN
        sm.GetService('ui').StopBlink(self.sr.busy)
        sm.GetService('ui').StopBlink(self.sr.glow)
        self.state = uix.UI_NORMAL
        self.IdleRamps()



    def SetRepairing(self):
        self.sr.glow.state = uix.UI_DISABLED
        self.sr.glow.color.r = 1.0
        self.sr.glow.color.g = 1.0
        self.sr.glow.color.b = 1.0
        self.sr.glow.color.a = 1.0
        sm.GetService('ui').BlinkSpriteA(self.sr.glow, 0.9, 2500, None, passColor=0)
        self.state = uix.UI_NORMAL



    def RemoveRepairing(self):
        sm.GetService('ui').StopBlink(self.sr.glow)
        self.sr.glow.color.r = 0.24
        self.sr.glow.color.g = 0.67
        self.sr.glow.color.b = 0.16
        self.sr.glow.color.a = 0.75
        self.sr.glow.state = uix.UI_HIDDEN



    def HiliteOn(self):
        self.sr.hilite.state = uix.UI_DISABLED



    def HiliteOff(self):
        self.sr.hilite.state = uix.UI_HIDDEN



    def GetEffectByName(self, effectName):
        for key in self.sr.moduleInfo.effects.iterkeys():
            effect = self.sr.moduleInfo.effects[key]
            if (effect.effectName == effectName):
                return effect




    def Update(self, effectState):
        if ((not self) or self.destroyed):
            return 
        if not self.stateManager.IsItemLoaded(self.id):
            return 
        if (self.def_effect and (effectState.effectName == self.def_effect.effectName)):
            if effectState.start:
                self.SetActive()
            else:
                self.SetIdle()
        effect = self.GetEffectByName(effectState.effectName)
        if (effect and (effect.effectCategory == const.dgmEffOverload)):
            self.ShowOverload(effect.isActive)
        if (effectState.effectName == 'online'):
            if effectState.active:
                self.ShowOnline()
            else:
                self.ShowOffline()
        if ((effect.effectCategory in [const.dgmEffTarget,
         const.dgmEffActivation,
         const.dgmEffArea]) and (effect.effectID != const.effectOnline)):
            if ((not effectState.active) and (self.quantity == 0)):
                self.AutoReload()
        self.UpdateInfo()



    def ActivateEffect(self, effect, targetID = None, ctrlRepeat = 0):
        if ((effect and (effect.effectName == 'useMissiles')) or ((effect.effectName == 'warpDisruptSphere') and (self.charge is not None))):
            if (self.charge is None):
                return 
            RELEVANTEFFECT = sm.GetService('godma').GetStateManager().GetDefaultEffect(self.charge.typeID)
        else:
            RELEVANTEFFECT = effect
        if (RELEVANTEFFECT and ((not targetID) and (RELEVANTEFFECT.effectCategory == 2))):
            targetID = sm.GetService('target').GetActiveTargetID()
            if not targetID:
                sm.GetService('target').OrderTarget(self)
                uthread.new(self.BlinkIcon)
                self.waitingForActiveTarget = 1
                return 
        if self.sr.Get('moduleinfo'):
            for key in self.sr.moduleInfo.effects.iterkeys():
                checkeffect = self.sr.moduleInfo.effects[key]
                if (checkeffect.effectName == 'online'):
                    if not checkeffect.isActive:
                        self._ChangeOnline(1)
                    break

        if effect:
            michelle = sm.GetService('michelle')
            bp = michelle.GetBallpark()
            ball = bp.GetBall(targetID)
            item = bp.GetInvItem(targetID)
            if RELEVANTEFFECT.isOffensive:
                if not sm.GetService('consider').DoAttackConfirmations(targetID, RELEVANTEFFECT):
                    return 
            elif not (RELEVANTEFFECT.isAssistance and sm.GetService('consider').DoAidConfirmations(targetID)):
                return 
            repeats = (ctrlRepeat or self.autorepeat)
            if not self.IsEffectRepeatable(effect, 1):
                repeats = 0
            if not self.charge:
                self.stateManager.ChangeAmmoTypeForModule(self.sr.moduleInfo.itemID, None)
            effect.Activate(targetID, repeats)



    def DeactivateEffect(self, effect):
        self.SetDeactivating()
        try:
            effect.Deactivate()
        except UserError, e:
            if (e.msg == 'EffectStillActive'):
                if sm.GetService('machoNet').GetClientConfigVals().get('fixStuckModules'):
                    if not self.isPendingUnlockForDeactivate:
                        self.isPendingUnlockForDeactivate = True
                        uthread.new(self.DelayButtonUnlockForDeactivate, e.dict['timeLeft'])
            raise 



    def DelayButtonUnlockForDeactivate(self, sleepTimeSec):
        blue.pyos.synchro.Sleep((sleepTimeSec * 1000))
        if (self.state == uix.UI_DISABLED):
            self.state = uix.UI_NORMAL
        self.isPendingUnlockForDeactivate = False



    def OnStateChange(self, itemID, flag, true, *args):
        if (self and (true and ((flag == state.activeTarget) and self.waitingForActiveTarget))):
            self.waitingForActiveTarget = 0
            self.ActivateEffect(self.def_effect, itemID)
            sm.GetService('target').CancelTargetOrder(self)



    def GetModuleType(self):
        return (self.sr.moduleInfo.typeID, self.sr.moduleInfo.itemID)



    def ActivateRamps(self):
        if ((not self) or self.destroyed):
            return 
        if self.ramp_active:
            self.UpdateRamps()
            return 
        self.DoActivateRamps()



    def DeActivateRamps(self):
        self.UpdateRamps()



    def IdleRamps(self):
        self.ramp_active = False
        shiplayer = uicore.layer.shipui
        if not shiplayer:
            return 
        moduleID = self.sr.moduleInfo.itemID
        rampTimers = shiplayer.sr.rampTimers
        if rampTimers.has_key(moduleID):
            del rampTimers[moduleID]
        self.sr.ramps.state = uix.UI_HIDDEN



    def UpdateRamps(self):
        self.DoActivateRamps()



    def DoActivateRamps(self):
        if self.ramp_active:
            return 
        uthread.new(self.DoActivateRampsThread)



    def DoActivateRampsThread(self):
        if ((not self) or self.destroyed):
            return 
        self.ramp_active = True
        self.sr.ramps.state = uix.UI_DISABLED
        (startTime, durationInMilliseconds,) = self.GetDuration()
        if (durationInMilliseconds <= 0):
            return 
        portionDone = ((blue.os.TimeDiffInMs(startTime) % durationInMilliseconds) / durationInMilliseconds)
        rampUpInit = min(1.0, max(0.0, (portionDone * 2)))
        rampDownInit = min(1.0, max(0.0, ((portionDone * 2) - 1.0)))
        while (self and ((not self.destroyed) and self.ramp_active)):
            (dummy, durationInMilliseconds,) = self.GetDuration()
            halfTheTime = (durationInMilliseconds / 2.0)
            funcs = [(self.SetRampUpValue, rampUpInit), (self.SetRampDownValue, rampDownInit)]
            rampUpInit = rampDownInit = 0.0
            for (i, (func, percent,),) in enumerate(funcs):
                init = percent
                if ((not self) or self.destroyed):
                    break
                if (i == 0):
                    self.sr.rightRamp.transform.RotationZ(math.pi)
                    self.sr.rightShadowRamp.transform.RotationZ(math.pi)
                    self.sr.leftRamp.transform.RotationZ(math.pi)
                    self.sr.leftShadowRamp.transform.RotationZ(math.pi)
                else:
                    self.sr.leftRamp.transform.RotationZ(0)
                    self.sr.leftShadowRamp.transform.RotationZ(0)
                    self.sr.rightRamp.transform.RotationZ(math.pi)
                    self.sr.rightShadowRamp.transform.RotationZ(math.pi)
                while not self.destroyed:
                    prePercent = percent
                    try:
                        percent = min(((blue.os.TimeDiffInMs(startTime) % halfTheTime) / halfTheTime), 1.0)
                    except:
                        percent = 1.0
                    if (prePercent > percent):
                        break
                    curValue = mathUtil.Lerp(init, 1.0, percent)
                    func(curValue)
                    blue.pyos.synchro.Yield()
                    if (self and ((not self.destroyed) and (not self.ramp_active))):
                        func(1.0)
                        break


            startTime += long((durationInMilliseconds * const.dgmTauConstant))
            if ((not self) or (self.destroyed or self.InLimboState())):
                break




    def InLimboState(self):
        for each in ['goingOnline',
         'waitingForActiveTarget',
         'changingAmmo',
         'reloadingAmmo',
         'isDeactivating']:
            if getattr(self, each, False):
                return True

        return False



    def GetRampStartTime(self):
        shiplayer = uicore.layer.shipui
        if not shiplayer:
            return 
        else:
            moduleID = self.sr.moduleInfo.itemID
            rampTimers = shiplayer.sr.rampTimers
            if not rampTimers.has_key(moduleID):
                now = blue.os.GetTime()
                default = getattr(self.def_effect, 'startTime', now)
                if (blue.os.TimeDiffInMs(default) > 1000.0):
                    rampTimers[moduleID] = default
                else:
                    rampTimers[moduleID] = now
            return rampTimers[moduleID]



    def GetDuration(self):
        rampStartTime = self.GetRampStartTime()
        durationInMilliseconds = 0.0
        attr = cfg.dgmattribs.GetIfExists(getattr(self.def_effect, 'durationAttributeID', None))
        item = self.stateManager.GetItem(self.def_effect.itemID)
        if (item is None):
            return (0, 0.0)
        else:
            if attr:
                durationInMilliseconds = self.stateManager.GetAttribute(self.def_effect.itemID, attr.attributeName)
            if not durationInMilliseconds:
                durationInMilliseconds = getattr(self.def_effect, 'duration', 0.0)
            return (rampStartTime, durationInMilliseconds)



    def SetRampUpValue(self, value):
        self.sr.leftRamp.transform.RotationZ((math.pi - (math.pi * value)))
        self.sr.leftShadowRamp.transform.RotationZ((math.pi - (math.pi * value)))



    def SetRampDownValue(self, value):
        self.sr.rightRamp.transform.RotationZ((math.pi - (math.pi * value)))
        self.sr.rightShadowRamp.transform.RotationZ((math.pi - (math.pi * value)))
        if (value == 1.0):
            self.sr.rightRamp.transform.RotationZ(math.pi)
            self.sr.rightShadowRamp.transform.RotationZ(math.pi)
            self.sr.leftRamp.transform.RotationZ(math.pi)
            self.sr.leftShadowRamp.transform.RotationZ(math.pi)




